clear textprogressbar; clear; clc;
%% Create session, Connect devices
PROJ_PATH = ['D:\code\AutoMeasurement\example\test_ziHF2' '\'];
session=MeasurementSession.SimpleMeasurement('owner',       'ZN', ...
                                             'name',        'PumpPowerControl',...
                                             'device_file', [PROJ_PATH 'device.dat'] );
                                         
session.addDescription( ...
    ['This Measurement performs PID control of Pump Power.' ] ...
    );

%%
zi = session.getDevice('dev1290');

%% Sweeper
clear textprogressbar;
swpr = zi.sweepModule(session);
ziDAQ('setInt', '/dev1290/pids/0/enable', 0); pause(1)

zi.setSigOutOffset('0', 0.0);
zi.setAuxOutSelect('0', -1).setAuxOutOffset('0', 0);
zi.enableSigOutAdd('0').fireSigOut('0');

swpr.setControl('gridnode', 'auxouts/0/offset', 'start', 0.0, 'stop', 10.0);
swpr.setMonitorNode('r');
swpr.subscribeChannel('0');
volt2power = swpr.run();
swpr.unsubscribeChannel();

zi.setAuxOutOffset('0', 0);
zi.silenceSigOut('0');

ctrl_volt = volt2power.dev1290.demods.sample{1}.grid;
pd_volt =  volt2power.dev1290.demods.sample{1}.r;

%% Scope
clear textprogressbar;
setPID();
zi.setSigOutOffset('0', 0.8).fireSigOut('0');

scope = zi.scopeModule(session); 

ziDAQ('setInt', '/dev1290/pids/0/enable', 0); pause(0.1);
scopeOpen = getScopeData(scope);

ziDAQ('setInt', '/dev1290/pids/0/enable', 1); pause(0.1);
scopeClose = getScopeData(scope);

%% Plotter
clear textprogressbar;
plotter=zi.plotterModule(session);

ziDAQ('setInt', '/dev1290/pids/0/enable', 0); pause(0.1);
plotter.setMonitorNode('x');
demod_Open_all = plotter.run('0', 'total_duration', 5.0);
demod_Open = plotter.getDataNode('r');

ziDAQ('setInt', '/dev1290/pids/0/enable', 1); pause(0.1);
plotter.setMonitorNode('x');
demod_Close_all = plotter.run('0', 'total_duration', 5.0);
demod_Close = plotter.getDataNode('r');

%% Spectrum
clear textprogressbar;
spectrum = zi.spectrumModule(session);

spectrum.setControl();
spectrum.setParam('spectrum/frequencyspan', 20e3);
spectrum.setParam('grid/cols', 4096);

ziDAQ('setInt', '/dev1290/pids/0/enable', 0); pause(0.1);
spectrum.subscribeChannel('0', 'R.fft.abs.avg');
spect_Open_all = spectrum.run();
spectrum.unsubscribeChannel();

ziDAQ('setInt', '/dev1290/pids/0/enable', 1); pause(0.1);
spectrum.subscribeChannel('0', 'R.fft.abs.avg');
spect_Close_all = spectrum.run();
spectrum.unsubscribeChannel();

spect_data_Open = get_Spectrum_Data(spect_Open_all);
spect_data_Close = get_Spectrum_Data(spect_Close_all);

%% dynamics
h = ziDAQ('dataAcquisitionModule');
ziDAQ('set', h, 'dataAcquisitionModule/triggernode', '/dev1290/demods/0/sample.R');
ziDAQ('set', h, 'dataAcquisitionModule/device', 'dev1290');
ziDAQ('set', h, 'dataAcquisitionModule/bandwidth', 0.0000000);
ziDAQ('set', h, 'dataAcquisitionModule/hysteresis', 0.0000000);
ziDAQ('set', h, 'dataAcquisitionModule/level', 1.205);
ziDAQ('set', h, 'dataAcquisitionModule/endless', 0);
ziDAQ('set', h, 'dataAcquisitionModule/grid/cols', 512);
ziDAQ('set', h, 'dataAcquisitionModule/delay', -0.0005000);

ziDAQ('setDouble', '/dev1290/demods/0/rate', 200e3);
% step response
ziDAQ('subscribe', h, '/dev1290/demods/0/sample.R.avg');
ziDAQ('execute', h);
tic; triggered = 0;
ziDAQ('setDouble', '/dev1290/pids/0/setpoint', 1.200);
ziDAQ('setDouble', '/dev1290/sigouts/0/offset', 0.8);
while ~ziDAQ('finished', h)
    if toc > 0.1 && ~ triggered
        ziDAQ('setDouble', '/dev1290/pids/0/setpoint', 1.210);
        triggered=1;
    end
  pause(1);
  stepResponse = ziDAQ('read', h);
  fprintf('waiting for trigger %0.0f%%\n', ziDAQ('progress', h) * 100);
end
ziDAQ('finish', h);
ziDAQ('unsubscribe', h, '*');

pause(1);
% noise rejection
ziDAQ('subscribe', h, '/dev1290/demods/0/sample.R.avg');
ziDAQ('execute', h);
tic; triggered = 0;
ziDAQ('setDouble', '/dev1290/pids/0/setpoint', 1.200);
ziDAQ('setDouble', '/dev1290/sigouts/0/offset', 0.8);
while ~ziDAQ('finished', h)
    if toc > 0.1 && ~ triggered
        ziDAQ('setDouble', '/dev1290/sigouts/0/offset', 0.810);
        triggered=1;
    end
  pause(1);
  noiseReject = ziDAQ('read', h);
  fprintf('waiting for trigger %0.0f%%\n', ziDAQ('progress', h) * 100);
end
ziDAQ('finish', h);
ziDAQ('unsubscribe', h, '*');

response_data = get_Demode_Data(stepResponse);
noise_rj_data = get_Demode_Data(noiseReject);

%% Save Data
session.addMeasurementData('volt2power', volt2power);

session.addMeasurementData('scopeOpen', scopeOpen);
session.addMeasurementData('scopeClose', scopeClose);

session.addMeasurementData('demod_Open_All', demod_Open_all);
session.addMeasurementData('demod_close_All', demod_Close_all);
session.addMeasurementData('demod_Open', demod_Open);
session.addMeasurementData('demod_close', demod_Close);

session.addMeasurementData('spect_Open_all', spect_Open_all);
session.addMeasurementData('spect_Close_all', spect_Close_all);
session.addMeasurementData('spect_data_Open', spect_data_Open);
session.addMeasurementData('spect_data_Close', spect_data_Close);

session.addMeasurementData('stepResponse', stepResponse);
session.addMeasurementData('noiseReject', noiseReject);
session.addMeasurementData('response_data', response_data);
session.addMeasurementData('noise_rj_data', noise_rj_data);

session.close();
MeasurementSession.save(session);

%% Plot Data
figure;
subplot(4, 4, [1 2 5 6])
plot(ctrl_volt, pd_volt, 'bo-'); grid minor
xlabel('control voltage (V)'); ylabel('PD DemodR (V)');


subplot(4, 4, 3)
plot(scopeOpen.timePts*1e3, scopeOpen.signalPts); grid on;
legend(sprintf('Std_{open} = %5.3f mV', 1000*std(scopeOpen.signalPts)));
xlim(minmax(scopeOpen.timePts*1e3)); ylim(mean(scopeOpen.signalPts) + 7.0*[-std(scopeOpen.signalPts) std(scopeOpen.signalPts)] ); grid on;
xlabel('time (ms)');ylabel('Scope (V)');

subplot(4, 4, 4)
plot( scopeClose.timePts*1e3, scopeClose.signalPts);grid on;
legend(sprintf('Std_{close} = %5.3f mV', 1000*std(scopeClose.signalPts)));
xlim(minmax(scopeClose.timePts*1e3)); ylim(mean(scopeClose.signalPts) + 7.0*[-std(scopeClose.signalPts) std(scopeClose.signalPts)] ); grid on;
xlabel('time (ms)');ylabel('Scope (V)');

subplot(4, 4, [7 8])
semilogy(scopeOpen.flist/1e3, sqrt(scopeOpen.pxx), scopeClose.flist/1e3, sqrt(scopeClose.pxx) );
xlim(minmax(scopeOpen.flist.'/1e3)); ylim([1e-6 1]);
xlabel('Frequency (kHz)'); ylabel('FFT Scope (V)');grid on
legend({'open', 'close'})

subplot(4, 4, 9)
plot(demod_Open.time, demod_Open.value)
xlim(minmax(demod_Open.time)); ylim(mean(demod_Open.value) + 7.0*[-std(demod_Open.value) std(demod_Open.value)] );grid on;
legend(sprintf('Std_{open} = %5.3f mV',std(demod_Close.value)*1000 ))
xlabel('time (s)');ylabel('DemodR (V)');
subplot(4, 4, 10)
plot(demod_Close.time, demod_Close.value)
xlim(minmax(demod_Close.time)); ylim(mean(demod_Close.value) + 7.0*[-std(demod_Close.value) std(demod_Close.value)] ); grid on;
legend(sprintf('Std_{close} = %5.3f mV', std(demod_Close.value)*1000 ))
xlabel('time (s)');ylabel('DemodR (V)');

subplot(4, 4, [13 14])
loglog(spect_data_Open.freq, spect_data_Open.value, spect_data_Close.freq, spect_data_Close.value)
xlabel('Frequency (Hz)'); ylabel('FFT demodR (V)'); grid on;
xlim(minmax(spect_data_Open.freq) ); ylim([1e-6 1]);
legend({'open', 'close'})

subplot(4, 4, [11 12])
plot(response_data.time*1e3, response_data.value, 'r.-');grid on;
legend(sprintf('step response,\nset value %5.3fV -> %5.3fV', 1.2, 1.21),'Location','southeast')
xlabel('time (ms)');ylabel('DemodR (V)');
xlim(minmax(response_data.time*1e3) ); 
subplot(4, 4, [15 16])
plot(noise_rj_data.time*1e3, noise_rj_data.value, 'b.-');grid on;
legend(sprintf('noise rejection,\n control voltage %5.3fV -> %5.3fV', 8, 8.1))
xlim(minmax(response_data.time*1e3) ); 
xlabel('time (ms)');ylabel('DemodR (V)');
%% functions
function data = getScopeData(scope)
    h = scope.hdl;
    scope.setMode('time');
    ziDAQ('setInt', '/dev1290/scopes/0/time', 10);
    ziDAQ('subscribe', h, '/dev1290/scopes/0/wave');
    ziDAQ('setInt', '/dev1290/scopes/0/enable', 1);
    ziDAQ('execute', h);
    pause(1);
    resultOpen = ziDAQ('read', h);
    ziDAQ('setInt', '/dev1290/scopes/0/enable', 0);
    ziDAQ('finish', h);
    ziDAQ('unsubscribe', h, '*');

    for k=1:1 %length(result1.dev1290.scopes.wave)
        data.signalPts = sqrt(2.0)*resultOpen.dev1290.scopes.wave{k}.wave;
        data.timePts = resultOpen.dev1290.scopes.wave{k}.dt*double(0:resultOpen.dev1290.scopes.wave{1}.totalsamples-1);
    end
    fs = 204800; npts = length(data.signalPts);
    [data.pxx, data.flist] = periodogram(data.signalPts, hamming(npts), npts, fs,'power');

end

% function plot_Scope_data(data_open, data_close)
%     subplot(2, 2, 1)
%     plot(data_open.timePts, data_open.signalPts);
%     title(sprintf('Std_{open} = %f(mV)', 1000*std(data_open.signalPts)));
% 
%     subplot(2, 2, 2)
%     plot( data_close.timePts, data_close.signalPts);
%     title(sprintf('Std_{close} = %f(mV)', 1000*std(data_close.signalPts)));
% 
%     subplot(2, 2, [3 4])
%     semilogy(data_open.flist/1e3, sqrt(data_open.pxx), data_close.flist/1e3, sqrt(data_close.pxx) );
%     xlim(minmax(data_open.flist.'/1e3)); ylim([1e-6 1]);
%     xlabel('Frequency (kHz)'); ylabel('V');grid on
% end

function setPID()
    ziDAQ('setInt', '/dev1290/pids/0/input', 2);
    ziDAQ('setDouble', '/dev1290/pids/0/setpoint', 1.2);
    ziDAQ('setDouble', '/dev1290/pids/0/demod/timeconstant', ziBW2TC(10e3, 4) );
    ziDAQ('setInt', '/dev1290/pids/0/demod/order', 4);
    ziDAQ('setDouble', '/dev1290/pids/0/demod/harmonic', 1);
    ziDAQ('setInt', '/dev1290/pids/0/output', 3);
    ziDAQ('setInt', '/dev1290/pids/0/outputchannel', 0);
    ziDAQ('setDouble', '/dev1290/pids/0/center', 0);
    ziDAQ('setDouble', '/dev1290/pids/0/range', 2);
    ziDAQ('setDouble', '/dev1290/pids/0/p', 3.018);
    ziDAQ('setDouble', '/dev1290/pids/0/i', 122.3e3);
    ziDAQ('setDouble', '/dev1290/pids/0/d', 0);
    ziDAQ('setInt', '/dev1290/pids/0/enable', 0); 
end

function data = get_Spectrum_Data(raw_data)
    sample = raw_data.dev1290.demods.sample_r_fft_abs_avg{1};
    data.freq=double(0:(sample.header.gridcols-1))*sample.header.gridcoldelta;
    data.value = sample.value;
end

function data = get_Demode_Data(raw_data)
    clockbase = double(ziDAQ('getInt','/dev1290/clockbase'));
    sample = raw_data.dev1290.demods.sample_r_avg{1};
    data.time = (double(sample.timestamp)-double(sample.timestamp(1)))/clockbase;
    data.value = sample.value;
end